﻿using Masuit.Tools.Reflection;
using Mohe.Scada.Util.Attr;
using Mohe.Scada.Util.Models;
using System.Collections;
using System.Reflection;

namespace Mohe.Scada.Common
{
    public static class TagExtension
    {
        public static bool IsArrayOrList(this Type that)
        {
            return !(that == null) && (that.IsArray || typeof(IList).IsAssignableFrom(that));
        }

        public static void ScanVarNames(this object obj, Dictionary<string, Tag> varNames, string pre = "")
        {
            if (obj == null)
            {
                return;
            }
            Type clazz = obj.GetType();
            object[] attrs = clazz.GetCustomAttributes(typeof(SubAttribute), true);
            string prefix = string.Empty;
            int sort = 0;
            if (attrs != null && attrs.Length > 0)
            {
                SubAttribute attr = (SubAttribute)attrs[0];
                if (!string.IsNullOrEmpty(attr.Prefix))
                {
                    int id = 0;

                    try
                    {
                        id = obj.GetProperty<int>(attr.Key);
                    }
                    catch
                    {
                        id = obj.GetProperty<short>(attr.Key);
                    }
                    prefix = $"{pre}{attr.Prefix}{id}.";
                    sort = id;
                }
            }
            if (clazz.IsGenericType)
            {
                var list = obj as IEnumerable<object>;
                foreach (var it in list)
                {
                    ScanVarNames(it, varNames, prefix);
                }

            }
            PropertyInfo[] properties = clazz.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                string propertyName = pi.Name;
                if (pi.PropertyType.IsArrayOrList())
                {
                    IEnumerable lst = pi.GetValue(obj, null) as IEnumerable<object>;
                    if (lst != null)
                    {
                        foreach (var it in lst)
                        {
                            ScanVarNames(it, varNames, prefix);
                        }
                    }
                    continue;

                }
                var attr = (SubAttribute)pi.GetCustomAttribute(typeof(SubAttribute), false);
                if (attr != null)
                {
                    var dataType = EnumDataType.Bool;
                    if (varNames.ContainsKey($"{prefix}{propertyName}"))
                    {
                        varNames.Remove($"{prefix}{propertyName}");
                    }

                    if (pi.PropertyType == typeof(bool))
                        dataType = EnumDataType.Bool;
                    else if (pi.PropertyType == typeof(byte))
                        dataType = EnumDataType.Byte;
                    else if (pi.PropertyType == typeof(short))
                        dataType = EnumDataType.Int16;
                    else if (pi.PropertyType == typeof(ushort))
                        dataType = EnumDataType.Uint16;
                    else if (pi.PropertyType == typeof(int))
                        dataType = EnumDataType.Int32;
                    else if (pi.PropertyType == typeof(uint))
                        dataType = EnumDataType.Uint32;
                    else if (pi.PropertyType == typeof(double))
                        dataType = EnumDataType.Double;
                    else if (pi.PropertyType == typeof(decimal))
                        dataType = EnumDataType.Double;
                    else if (pi.PropertyType == typeof(float))
                        dataType = EnumDataType.Float;

                    var deviceVariable = new Tag
                    {
                        VarName = $"{prefix}{propertyName}",
                        Pos = 0,
                        Bit = 0,
                        TypeName = pi.PropertyType,
                        Model = obj,
                        FieldName = propertyName,
                        DataType = dataType,
                        ProtectType = attr.ProtectType,
                        IsWarning = attr.IsWarning,
                        WarningContent = attr.IsWarning ? string.Format(attr.ErrorMessage, sort) : string.Empty,
                        WarningType = 0,
                        NeedNegate = false,
                        Sort = sort,
                    };
                    varNames.Add($"{prefix}{propertyName}", deviceVariable);
                }
            }
        }
    }
}
